import time
from PyQt5.QtCore import *
from guiqwt.builder import make

class CScopeDisplay():
    
    def __init__(self, displayWidget, dlgParent = None):

        self.displayWidget = displayWidget
        
        self.curves = [make.curve([0], [0], color = 'blue'), 
                       make.curve([0], [0], color = 'red'), 
                       make.curve([0], [0], color = 'yellow'), 
                       make.curve([0], [0], color = 'green'), 
                       make.curve([0], [0], color = 'brown'), 
                       make.curve([0], [0], color = 'black'), 
                       make.curve([0], [0], color = 'pink'), 
                       make.curve([0], [0], color = 'purple'), 
                       ]
        self.plot = self.displayWidget.get_plot()
        
        for curve in self.curves:
            self.plot.add_item(curve)
            
        self.plot.add_item(make.legend('TR'))
        
        self.timeSpan = 20
        self.plot.set_axis_limits('bottom', 0, self.timeSpan)
        
        
    def ReInit(self, chList):
        
        index = 0
        
        # Delete all items from plot
        for curve in self.curves:
            try:
                self.plot.del_item(curve)
            except:
                continue
        
        
        for ch in chList:            
            self.curves[index].set_data([0], [0])
            self.curves[index].setTitle(ch.name)
            if ch.active:
                self.plot.add_item(self.curves[index])
            index = index + 1
            
        #self.plot.set_axis_limits('bottom', 0, self.timeSpan)
        
        
    def UpdateChannel(self, chIndex, x, y):       
        self.curves[chIndex].set_data(x, y)                


    def AutoScale(self):
        self.plot.do_autoscale()


class CScopeChannel():
    
    def __init__(self):

        self.pointer = 0
        self.data = None
        self.name = 'data1'
        self.addr = 0
        self.size = 1
        self.type = 'Uint'
        self.scale = 1.0
        self.offset = 0.0
        self.slaveAddr = 1
        self.isParam = False
        self.active = False

    def ReallocateBuffer(self, size):
        
        try:
            del self.data
        except:
            pass
        
        self.data = [0] * size
        self.pointer = 0


    def append(self, datum):
        
        self.data[self.pointer] = datum
        self.pointer = self.pointer + 1
        if self.pointer >= len(self.data):
            self.pointer = 0


    def length(self):        
        return self.pointer


class CSampleThread(QThread):

    def __init__(self, host, parent = None):
        super(CSampleThread, self).__init__(parent)

        self.host = host
        self.hold = False
        self.holded = False

    def run(self):

        #self.timer.start(5)
        self.hold = False
        self.holded = False

        while self.hold == False:
            self.host.Sample()
            time.sleep(0.01)
            
        self.holded = True

    def stop(self):
        #self.timer.stop()
        self.hold = True
        
    def Stopped(self):
        return self.holded
     


class CScope:
    
    MAX_DATA_SIZE = 8000*600
    
    def __init__(self, display, chList, protocol, mode, parent = None):
        
        self.chList = chList
        self.display = display
        display.ReInit(chList)
        
        for ch in chList:
            
            if ch.active == True:
                bufferSize = CScope.MAX_DATA_SIZE
            else:
                bufferSize = 0

            ch.ReallocateBuffer(bufferSize)
            
        self.xAxies = CScopeChannel()
        self.xAxies.ReallocateBuffer(CScope.MAX_DATA_SIZE)
            
        protocol.channelList = chList
        protocol.xAxies = self.xAxies        
        self.protocol = protocol

        self.sampleThread = CSampleThread(self)
        
        self.timerInterval = 50
        self.timer = QTimer()
        self.timer.timeout.connect(self.On_Timer)    
        
        self.hold = False
        self.mode = mode
        
        if mode == 'F':
            self.maxSpan = 40000
        else:
            self.maxSpan = 500

        
    def Start(self):
        
        self.protocol.Start()
        self.sampleThread.start()
        
        self.timer.start(self.timerInterval)
        #self.btnStart.setText('Stop')   
        #self.started = True
        self.prevClock = time.clock()
        
    def Sample(self):
        try:
            self.protocol.GetData()
        except Exception as e:
            print(str(e))
        
    def Stop(self):
        
        self.sampleThread.stop()
        # Wait for the thread stop
        time.sleep(0.3)
        #self.device.close()
        self.timer.stop()
        self.Finalize()
        
    def Stopped(self):
        return self.sampleThread.Stopped()
        
        
    def Hold(self, newState):
        self.hold = newState
        
        
    def On_Timer(self): 
        
        minCount = CScope.MAX_DATA_SIZE
        for ch in self.chList:
            if ch.active == True:
                count = ch.length()
                if count < minCount:
                    minCount = count
        
        if minCount > self.maxSpan:
            start = minCount - self.maxSpan
        else:
            start = 0
            
        end = minCount
        
        if self.hold == False:
            #self.dataManager.SampleData()
            self.UpdateDisplay(start,  end)
                
     
    def UpdateDisplay(self, startIndex,  endIndex):
        
        for index in range(0, len(self.chList)):
            if self.chList[index].active == True:
                self.display.UpdateChannel(index, self.xAxies.data[startIndex:endIndex], self.chList[index].data[startIndex:endIndex])
            
        self.display.AutoScale()
     
        
    def Finalize(self):
        
        for index in range(0, len(self.chList)):
            if self.chList[index].active == True:
                self.display.UpdateChannel(index, self.xAxies.data[0:self.xAxies.length()], self.chList[index].data[0:self.chList[index].length()])
            
        self.display.AutoScale()
        

